package gitobject;

import fileoperation.FileReader;
import sha1.SHA1;
import repository.Repository;
import zlib.ZLibUtils;

import java.io.*;
import java.text.SimpleDateFormat;
import java.util.Date;

public class Commit extends GitObject{
    protected String tree; 		// the sha1 value of present committed tree
    protected String parent; 	// the sha1 value of the parent commit
    protected String author; 	// the author's name and timestamp
    protected String committer; // the committer's info
    protected String message; 	// the commit memo

    public String getParent(){return parent;}
    public String getTree(){return tree;}
    public String getAuthor(){return author;}
    public String getCommitter(){return committer;}
    public String getMessage(){return message;}

    public Commit(){}
    /**
     * Construct a commit directly from a file.
     * @param
     * author, committer, message参数在git commit命令里创建
     * @throws Exception
     */

    public Commit(String treePath, String author, String committer, String message) throws Exception {
        this.fmt = "commit"; 	//type of object
        this.tree = new Tree(new File(treePath)).getKey();
        this.parent = getLastCommit() == null ? "" : getLastCommit(); //null means there is no parent commit.
        this.author = author;
        this.committer = committer;
        this.message = message;

        /*Content of this commit, like this:
         *tree bd31831c26409eac7a79609592919e9dcd1a76f2
         *parent d62cf8ef977082319d8d8a0cf5150dfa1573c2b7
         *author xxx  1502331401 +0800
         *committer xxx  1502331401 +0800
         *修复增量bug
         * */
        this.value = "tree " + this.tree + "\nparent " + this.parent+ "\nauthor " + this.author + "\ncommitter " + this.committer + "\n" + this.message;

        key = genKey();
        compressWrite();
    }

    /**
     * Construct a commit from a built tree.
     * @param
     * author, committer, message参数在git commit命令里创建
     * @throws Exception
     */
    public Commit(Tree t, String author, String committer, String message) throws Exception {
        this.fmt = "commit"; 	//type of object
        this.tree = t.getKey();
        this.parent = getLastCommit() == null ? "" : getLastCommit(); //null means there is no parent commit.
        this.author = author;
        this.committer = committer;
        this.message = message;

        /*Content of this commit, like this:
         *tree bd31831c26409eac7a79609592919e9dcd1a76f2
         *parent d62cf8ef977082319d8d8a0cf5150dfa1573c2b7
         *author xxx  1502331401 +0800
         *committer xxx  1502331401 +0800
         *修复增量bug
         * */
        this.value = "tree " + this.tree + "\nparent " + this.parent+ "\nauthor " + this.author + "\ncommitter " + this.committer + "\n" + this.message;
        key = genKey();
//        compressWrite();
    }

    /**
     * Deserialize the commit object from its key(commitId)
     * @param commitId
     * @throws IOException
     */
    // 按blob反序列的逻辑，通过commit的key值反序列出commit的各项属性信息
    // 先找到该commit文件，然后反序列化，再从反序列的value读取出来各项值。
    public Commit(String commitId) throws IOException {
        File file = new File(path + File.separator + commitId.substring(0,2)+ File.separator + commitId.substring(2));
        if(file.exists()){
            this.fmt = "commit";
            this.key = commitId;
            FileInputStream input = new FileInputStream(file);
            byte[] byt = ZLibUtils.decompress(input);
            this.value = new String(byt);
            input.close();
            /*Content of this commit, like this:
             *tree bd31831c26409eac7a79609592919e9dcd1a76f2
             *parent d62cf8ef977082319d8d8a0cf5150dfa1573c2b7
             *author xxx  1502331401 +0800
             *committer xxx  1502331401 +0800
             *修复增量bug
             * */
            this.parent = FileReader.readCommitParent(this.value);
            this.tree = FileReader.readCommitTree(this.value);
            this.author = FileReader.readCommitAuthor(this.value);
            this.committer = FileReader.readCommitter(this.value);
            this.message = FileReader.readCommitMsg(this.value);
        }
    }

    /**
     *
     * Generate the hash value of this commit.
     * @return key
     * */
    public String genKey() throws Exception {
        key = SHA1.getHash(value);
        return key;
    }


    /**
     * Get the parent commit from the HEAD file.
     * @return
     * @throws IOException
     */
    public static String getLastCommit() throws IOException {
        File HEAD = new File(Repository.getGitDir() + File.separator + "HEAD");
        if(getValue(HEAD).length()>0){
            String path = getValue(HEAD).substring(5).replace("\n", "");
            // branchFile存储当前分支的commit信息
            File branchFile = new File(Repository.getGitDir() + File.separator + path);

            if (branchFile.isFile()) {
                return getValue(branchFile);
            } else {
                return null;
            }
        }else{
            return null;
        }
    }

    // 追溯当前commit的信息
    public static void printLogs(Commit commit) throws IOException {
        while(commit !=null ){
            //设置日期格式为“年-月-日 时:分:秒”
            SimpleDateFormat date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            //用keystore存放commit的key
            String commitInfo = commit.getFmt()+" " + commit.getKey() + "\nAuthor: " + commit.getCommitter() + "\nDate: " + date.format(new Date()) + "\n";
            System.out.println(commitInfo);
            String parentId = commit.getParent();
            if(parentId.length()>0){
                commit = Commit.deserialize(parentId);
            }else{
                return;
            }
        }
    }


    @Override
    public String toString() {

        return "  - commit :\t" + key + '\n' +
                "  - tree :\t\t" + tree + '\n' +
                "  - parent :\t" + parent + '\n' +
                "  - author :\t" + author + '\n' +
                "  - committer :\t" + committer + '\n' +
                "  - message :\t" + message +'\n' ;
    }

    public static Commit deserialize(String Id) throws IOException {
        Commit commit = new Commit();
        commit.fmt = "commit";
        try{
            File file = new File(path + File.separator + Id.substring(0,2) + File.separator + Id.substring(2));
            if(file.exists()){
                commit.key = Id;
                FileInputStream input = new FileInputStream(file);
                byte[] byt = ZLibUtils.decompress(input);
                commit.value = new String(byt);
                input.close();
                String [] arr = commit.value.split("\n");
                commit.tree=arr[0].substring(5);
                commit.parent=arr[1].substring(7);
                commit.author=arr[2].substring(7);
                commit.committer=arr[3].substring(10);
                commit.message=arr[4];
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return commit;
    }
}
